package com.ljx.itbbs.server.mall.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ljx.itbbs.common.domain.entity.UserEntity;
import com.ljx.itbbs.common.domain.vo.resp.PageResp;
import com.ljx.itbbs.common.utils.AssertUtil;
import com.ljx.itbbs.server.mall.dao.OrderDao;
import com.ljx.itbbs.server.mall.domain.entity.CouponEntity;
import com.ljx.itbbs.server.mall.domain.entity.OrderEntity;
import com.ljx.itbbs.server.mall.domain.enums.OrderTypeEnum;
import com.ljx.itbbs.server.mall.domain.enums.PaymentStatusEnum;
import com.ljx.itbbs.server.mall.domain.vo.req.OrderReq;
import com.ljx.itbbs.server.mall.domain.vo.req.OrderSaveReq;
import com.ljx.itbbs.server.mall.domain.vo.req.OrderSubmitReq;
import com.ljx.itbbs.server.mall.domain.vo.resp.OrderResp;
import com.ljx.itbbs.server.mall.event.OrderSubmitEvent;
import com.ljx.itbbs.server.mall.service.CouponRecordService;
import com.ljx.itbbs.server.mall.service.CouponService;
import com.ljx.itbbs.server.mall.service.OrderService;
import com.ljx.itbbs.server.mall.service.strategy.AbstractOrderHandler;
import com.ljx.itbbs.server.mall.service.strategy.OrderHandlerFactory;
import com.ljx.itbbs.server.mq.domain.mall.OrderMsgDto;
import com.ljx.itbbs.server.mq.service.RabbitMQProducer;
import com.ljx.itbbs.server.user.service.UserService;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.ljx.itbbs.server.mq.config.DlxMqConfig.ORDER_EXCHANGE;
import static com.ljx.itbbs.server.mq.config.DlxMqConfig.ORDER_QUEUE;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private UserService userService;

    @Autowired
    private CouponService couponService;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public OrderEntity getOrder(Long userId, String resourceId) {
        return orderDao.gerOrderByUIdAndObjId(userId, resourceId);
    }

    @Override
    public OrderEntity getOrder(Long orderId) {
        return orderDao.gerOrderById(orderId);
    }

    @Override
    public List<OrderEntity> batchOrder(Long userId, List<String> resIds) {
        return orderDao.batchOrderByUIdAndObjIds(userId, resIds);
    }

    @Override
    public Long saveOrder(Long userId, OrderSaveReq req) {
//        // 保存订单
        AbstractOrderHandler<?> orderHandler = OrderHandlerFactory.getStrategyNoNull(req.getType());
        Long orderId = orderHandler.saveOrder(req, userId);
//        // 添加过期时间
        rabbitTemplate.convertAndSend(ORDER_EXCHANGE, ORDER_QUEUE, new OrderMsgDto(orderId));

        return orderId;
    }

//    /**
//     * 处理待发送消息
//     * @return
//     */
//    private MessagePostProcessor messagePostProcessor() {
//        return new MessagePostProcessor() {
//            @Override
//            public Message postProcessMessage(Message message) throws AmqpException {
//                // 设置有效期30分钟
//                //message.getMessageProperties().setExpiration("1800000");
//                message.getMessageProperties().setExpiration("10000");
//                return message;
//            }
//        };
//    }

    @Override
    public void submitOrder(Long userId, OrderSubmitReq req) {
        Long orderId = req.getOrderId(), couponId = req.getCouponId();
        OrderEntity orderEntity = orderDao.getById(orderId);
        check(userId, orderEntity, couponId);
        // 修改订单状态
        orderEntity.setPaymentStatus(PaymentStatusEnum.OK.getType());
        orderDao.updateById(orderEntity);
        // 发布确认订单事件
        applicationEventPublisher.publishEvent(new OrderSubmitEvent(this, orderId, req.getCouponId()));
    }

    private void check(Long userId, OrderEntity orderEntity, Long couponId) {
        AssertUtil.isFalse(orderEntity.getPaymentStatus().equals(PaymentStatusEnum.LOSE.getType()), "订单已失效");
        AssertUtil.isFalse(orderEntity.getPaymentStatus().equals(PaymentStatusEnum.OK.getType()), "订单已支付");
        // 检查积分是否足够
        UserEntity userEntity = userService.getUserInfoById(userId);
        Integer couponNum = 0;
        // 若存在优惠券则需要加上优惠券的余额
        CouponEntity couponEntity = null;
        if (Objects.nonNull(couponId)){
            couponEntity = couponService.getUserCoupon(userId, couponId);
            AssertUtil.isNotEmpty(couponNum, "没有该优惠券");
            couponNum = couponEntity.getMoney();
        }
        AssertUtil.isFalse(userEntity.getIntegral() + couponNum < orderEntity.getMoney(), "积分不足");
    }

    @Override
    public PageResp<OrderResp> getUserOrderList(Long userId, OrderReq req) {
        IPage<OrderEntity> resp = orderDao.getOrderPage(userId, req);
        List<OrderResp> records = resp.getRecords().stream()
                .map(item -> {
                    OrderResp orderResp = BeanUtil.copyProperties(item, OrderResp.class);
                    orderResp.setTypeStr(OrderTypeEnum.of(item.getType()).getDesc());
                    orderResp.setPaymentStatusStr(PaymentStatusEnum.of(item.getPaymentStatus()).getDesc());
                    return orderResp;
                }).collect(Collectors.toList());

        return PageResp.<OrderResp>builder()
                .total(resp.getTotal())
                .list(records)
                .build();
    }

    @Override
    public void updatePaymentStatus(Long orderId, Integer type) {
        orderDao.updatePaymentStatus(orderId, type);
    }
}
